/*
 * Created on 2005-4-27
 *
 */
package util;

import java.io.Serializable;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;

import org.apache.commons.beanutils.PropertyUtils;


/**
 * @author 
 * Object-Relation转换核心类之一，每个实例对应一个java bean某一属性的OR转换
 */
public class ORProperty implements Serializable
{
    public final static int FIELD_TYPE_STRING = 0;
    public final static int FIELD_TYPE_BOOLEAN = 1;
    public final static int FIELD_TYPE_BYTE = 2;
    public final static int FIELD_TYPE_INT = 3;
    public final static int FIELD_TYPE_LONG = 4;
    public final static int FIELD_TYPE_FLOAT = 5;
    public final static int FIELD_TYPE_DOUBLE = 6;
    public final static int FIELD_TYPE_DATE = 7;
    public final static int FIELD_TYPE_ID = 8;
    public final static int FIELD_TYPE_TIMESTAMP = 9;
    
    private String propertyName;//做OR转换的java bean的一个属性名
    private boolean indexed;//该属性是否为序列型变量(java bean对于数组类型变量可以有形如get(i)/set(i, <<type>>)的函数)
    private String fieldName;//该属性对应的数据库表中的字段名
    private int fieldType;//该属性对应数据库表中的字段类型，以对应的java类型标识
    private boolean autoIncrement;//该属性是否由数据库系统维护，若是，则不出现在insert语句中

    /**
     * 静态函数,根据属性的Class属性返回相应的类型值(由上面各常量定义)
     * 
     * @param propertyClass
     * @return
     */
    public static int getType(Class propertyClass)
    {
        String className = propertyClass.getName();
        if (propertyClass.equals(String.class))return FIELD_TYPE_STRING;
        else if (className.equals("boolean"))return FIELD_TYPE_BOOLEAN;
        else if (className.equals("byte"))return FIELD_TYPE_BYTE;
        else if (className.equals("int"))return FIELD_TYPE_INT;
        else if (className.equals("long"))return FIELD_TYPE_LONG;
        else if (className.equals("float"))return FIELD_TYPE_FLOAT;
        else if (className.equals("double"))return FIELD_TYPE_DOUBLE;
        else if (propertyClass.equals(java.util.Date.class))return FIELD_TYPE_DATE;
        else if (propertyClass.equals(java.sql.Timestamp.class))return FIELD_TYPE_TIMESTAMP;
        return -1;
    }
    /**
     * 静态私有工具函数，用于生成sql语句
     * 
     * @param javaValue
     * @param fieldType
     * @return
     */
    private static String getSQLForm(Object javaValue, int fieldType)
    {
        if (javaValue == null)return null;
        StringBuffer sqlForm = new StringBuffer();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        //防止注入攻击,若传入参数类型为String,则去除其中全部引号
        if (javaValue instanceof String)
            javaValue = ((String)javaValue).replaceAll("'", "''");
        switch (fieldType)
        {
        	case FIELD_TYPE_STRING:
        	case FIELD_TYPE_BYTE:
        	    sqlForm.append("'");
        	    sqlForm.append(javaValue);
        	    sqlForm.append("'");
        	    break;
        	case FIELD_TYPE_DATE:
        	    sqlForm.append("'");
        	    sqlForm.append(dateFormat.format(javaValue));
        	    sqlForm.append("'");
        	    break;
        	case FIELD_TYPE_INT:
        	case FIELD_TYPE_LONG:
        	case FIELD_TYPE_FLOAT:
        	case FIELD_TYPE_DOUBLE:
        	case FIELD_TYPE_ID:
        	    sqlForm.append(javaValue);
        	    break;
        	case FIELD_TYPE_BOOLEAN:
        	    if (javaValue.equals(Boolean.TRUE))sqlForm.append(1);
        	    else if (javaValue.equals(Boolean.FALSE))sqlForm.append(0);
        	    else return null;
        	    break;
        	case FIELD_TYPE_TIMESTAMP:
        	    sqlForm.append("'");
        	    sqlForm.append(dateFormat.format(javaValue));
        	    sqlForm.append("'");
        	    break;
        }
        return sqlForm.toString();
    }
    
    public String getFieldName()
    {
        return fieldName;
    }
    public void setFieldName(String fieldName)
    {
        this.fieldName = fieldName;
    }
    public int getFieldType()
    {
        return fieldType;
    }
    public void setFieldType(int fieldType)
    {
        this.fieldType = fieldType;
    }
    public boolean isIndexed()
    {
        return indexed;
    }
    public void setIndexed(boolean indexed)
    {
        this.indexed = indexed;
    }
    public String getPropertyName()
    {
        return propertyName;
    }
    public void setPropertyName(String propertyName)
    {
        this.propertyName = propertyName;
    }
    public boolean isAutoIncrement()
    {
        return autoIncrement;
    }
    public void setAutoIncrement(boolean autoIncrement)
    {
        this.autoIncrement = autoIncrement;
    }
    
    /**
     * 将该实例对应的bean属性转化为某一sql语句中的一部分
     * 
     * @param bean
     * @return
     */
    public String getInsertForm(Object bean)
    {
        if (indexed)return null;
        Object value;
        try
        {
            value = PropertyUtils.getSimpleProperty(bean, propertyName);
        }
        catch (Exception e)
        {
            System.out.println("getInsertForm() in ORProperty:");
            System.out.println(e.getMessage());
            value = null;
        }
        return getSQLForm(value, fieldType);        
    }
    /**
     * 将该实例对应的bean属性转化为某一sql语句中的一部分
     * 
     * @param bean
     * @return
     */
    public String getInsertForm(Object bean, int index)
    {
        Object value;
        try
        {
            if (indexed)
                value = PropertyUtils.getIndexedProperty(bean, propertyName, index);
            else
                value = PropertyUtils.getSimpleProperty(bean, propertyName);
        }
        catch (Exception e)
        {
            System.out.println("getInsertForm(int) in ORProperty:");
            System.out.println(e.getMessage());
            value = null;
        }
        return getSQLForm(value, fieldType);
    }
    /**
     * 将该实例对应的bean属性转化为某一sql语句中的一部分
     * 
     * @param bean
     * @return
     */
    public String getUpdateForm(Object bean)
    {
        if (indexed)return null;
        StringBuffer updateForm = new StringBuffer();
        updateForm.append(fieldName);
        updateForm.append("=");
        updateForm.append(getInsertForm(bean));
        return updateForm.toString();
    }
    /**
     * 将该实例对应的bean属性转化为某一sql语句中的一部分
     * 
     * @param bean
     * @return
     */
    public String getUpdateForm(Object bean, int index)
    {
        StringBuffer updateForm = new StringBuffer();
        updateForm.append(fieldName);
        updateForm.append("=");
        updateForm.append(getInsertForm(bean, index));
        return updateForm.toString();       
    }
    /**
     * 将ResultSet当前行中对应于bean属性的值存入java bean中
     * 
     * @param bean
     * @param resultset
     */
    public void setPropertyValue(Object bean, ResultSet resultset)
    {
        if (indexed)return;
        try
        {
            Object value =  retrieveValue(resultset);
            if (value == null && (fieldType != FIELD_TYPE_STRING || fieldType != FIELD_TYPE_DATE))
                return;
            PropertyUtils.setProperty(bean, propertyName, value);
        }
        catch(Exception e)
        {
            System.out.println("setPropertyValue() in ORProperty:");
            System.out.println(e.getMessage());            
        }
    }
    /**
     * 将ResultSet当前行中对应于bean属性的值存入java bean中
     * 
     * @param bean
     * @param resultset
     */
    public void setPropertyValue(Object bean, ResultSet resultset, int index)
    {
        try
        {
            if (indexed)
                PropertyUtils.setIndexedProperty(bean, propertyName, index, retrieveValue(resultset));
            else
                PropertyUtils.setSimpleProperty(bean, propertyName, retrieveValue(resultset));
        }
        catch(Exception e)
        {
            System.out.println("setPropertyValue() in ORProperty:");
            System.out.println(e.getMessage());            
        }
    }
    private Object retrieveValue(ResultSet resultset)
    {
        Object value = null;
        try
        {
            switch (fieldType)
            {
            	case FIELD_TYPE_STRING:
            	case FIELD_TYPE_ID:
            	    value = preprocessString(resultset.getString(fieldName));
            	    break;
            	case FIELD_TYPE_BOOLEAN:
            	    value = new Boolean(resultset.getBoolean(fieldName));
            	    break;
            	case FIELD_TYPE_BYTE:
            	    value = new Byte(resultset.getByte(fieldName));
            	    break;
            	case FIELD_TYPE_INT:
            	    value = new Integer(resultset.getInt(fieldName));
            	    break;
            	case FIELD_TYPE_LONG:
            	    value = new Long(resultset.getLong(fieldName));
            	    break;
            	case FIELD_TYPE_FLOAT:
            	    value = new Float(resultset.getFloat(fieldName));
            	case FIELD_TYPE_DOUBLE:
            	    value = new Double(resultset.getDouble(fieldName));
            	    break;
            	case FIELD_TYPE_DATE:
            	    value = resultset.getDate(fieldName);
            	    break;
            }
        }
        catch(Exception e)
        {
            //System.out.println("setPropertyValue() in ORProperty:");
            //System.out.println(e.getMessage());
            value = null;
        }
        return value;
    }
    //对字符串进行预处理，当字符串中不含有意义内容时令其为空
    public static String preprocessString(String inputString)
    {
        String outputString;
        if (inputString == null)
            return "";
        else
            outputString = inputString.trim();
        if (outputString.length() == 0)
            return "";
        else
            return outputString;
    }
}
